package com.guw.TestReflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        //通过反射获取类的Class对象
        //方式一:通过对象名称获取Class
        Class c1 = Class.forName("com.guw.TestReflection.User");
        //获取类的名字
        System.out.println(c1);
        //获取类的简单名字
        System.out.println(c1.getSimpleName());
        //方式二:通过对象获取Class
        User user1 = new User();
        Class c2 = user1.getClass();
        //方式三:通过类名.Class获取
        Class c3 = User.class;
        //一个类在内存中只有一个Class对象
        //一个类被加载后,类的整个结构都会被封装在Class对象中
        //每个实例都会记得自己是由哪个Class实例产生的
        //通过Class可以完整地得到一个类中所有被加载的结构
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());

        //获得父类的类型
        Class c4 = c1.getSuperclass();
        System.out.println(c4);

        //获得类的属性
        //获得指定属性的值,注意要抛异常!!
        Field name = c1.getDeclaredField("name");//获得指定属性的值
        System.out.println(name);
        //Field[] field = c1.getFields();//只能找到public属性
        Field[] fields = c1.getDeclaredFields();//能找到全部属性
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("==============================");

        //获取类的方法
        //公共的方法,包括继承的方法
        Method[] methods1 = c1.getMethods();
        for (Method method : methods1) {
            System.out.println(method);
        }
        System.out.println("================================");
        //获得本类的所有方法:
        Method[] declaredMethods = c1.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("===================================");
        //获得指定方法:需要放参数因为方法可能会重载,没有指定参数类型就无法指定方法
        Method getAge = c1.getMethod("getAge", null);
        Method setAge = c1.getMethod("setAge", int.class);
        System.out.println(getAge);
        System.out.println(setAge);
        System.out.println("====================================");

        //获得构造器
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("===============================");
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        System.out.println("==============================");
        Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
        System.out.println(constructor);
        System.out.println("===========================");
        //获得修饰符
        System.out.println(c1.getModifiers());



        /*//获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类加载器的父加载器:扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);

        //获取扩展类加载器的父加载器:根加载器(C/C++写的,加载不了)
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);

        //测试当前类是哪个加载器加载的
        ClassLoader classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);

        //获取系统类加载器的路径
        System.out.println(System.getProperty("java.class.path"));*/

        /*双亲委派机制:
        当某个类加载器需要加载某个.class文件时，它首先把这个任务委托给他的上级类加载器，
        递归这个操作，如果上级的类加载器没有加载，自己才会去加载这个类。*/


    }
}

//实体类
class User{
    private String name;
    private int id;
    private int age;

    public User() {
    }

    public User(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }
}